package com.demo.feifan.config;

import com.demo.feifan.aspect.DynamicDataSourceContextHolder;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@MapperScan(basePackages = "com.demo.feifan.mapper")
public class DataSourceConfig {

    /**
     * 创建pg数据源
     * @return
     */
    @Bean(name = "postgresDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.postgres")
    public DataSource postgresDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 创建clickhouse数据源
     * @return
     */
    @Bean(name = "clickhouseDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.clickhouse")
    public DataSource clickhouseDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 默认数据源
     * 原理
     * 当执行数据库操作时，Spring 会调用 AbstractRoutingDataSource 的路由逻辑
     * determineCurrentLookupKey() 方法返回当前线程中设置的数据源标识
     * 根据这个标识从 targetDataSources 映射中找到对应的实际数据源
     * 这样就完成了整个数据源切换的过程：切面设置 → ThreadLocal 存储 → AbstractRoutingDataSource 读取 → 返回对应数据源。
     *
     * @param postgresDataSource
     * @param clickhouseDataSource
     * @return
     */
    @Bean
    @Primary
    public DataSource dynamicDataSource(
            @Qualifier("postgresDataSource") DataSource postgresDataSource,
            @Qualifier("clickhouseDataSource") DataSource clickhouseDataSource) {

        AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                return DynamicDataSourceContextHolder.getDataSource();
            }
        };

        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("postgres", postgresDataSource);
        targetDataSources.put("clickhouse", clickhouseDataSource);
        routingDataSource.setTargetDataSources(targetDataSources);
        routingDataSource.setDefaultTargetDataSource(postgresDataSource);
        return routingDataSource;
    }

}
